package lock_mqtt

import (
	"encoding/json"
	"errors"
	"fmt"
	"regexp"
	"server/global"
	"server/global/mqtt/fsc"
	"server/model"
	"server/service"
	"server/utils"
	"strconv"
	"time"

	MQTT "github.com/eclipse/paho.mqtt.golang"
)

type AswData struct {
	AswCode string `json:"aswcode"`
	AswMsg  string `json:"aswmsg"`
}

// 设备状态变化处理
func StatusDeal(sn string, data AswData) error {
	// 根据sn查询设备信息
	d := &model.Device{Sn: sn}
	exist, _ := service.DeviceExistBySn(*d)
	if !exist {
		return errors.New(fmt.Sprintf("[%v]设备不存在, 无法更新设备状态~", sn))
	}
	device, err := service.DeviceGetBySn(*d)
	if err != nil {
		return err
	}
	if device.Tag == "infrared" {
		// fmt.Println("红外变化")
		if data.AswCode == fsc.CODE_INFRARED_GET_PEOPLE {
			if aswmsg, err_msg := strconv.Atoi(data.AswMsg); err_msg == nil {
				global.LOG.Debug(fmt.Sprintf("红外变化[%v]: %v", sn, data.AswMsg))
				// 修改状态
				device.Status = aswmsg
				err = service.DeviceEdit(*device)
				if err != nil {
					return err
				}
				// 添加记录
				dlog := &model.DeviceLog{DeviceID: device.ID, Status: aswmsg, Value: ""}
				err = service.DeviceLogAdd(*dlog)
				if err != nil {
					return err
				}
			}
		}
	}
	if device.Tag == "door" {
		// fmt.Println("门禁变化")
		if data.AswCode == fsc.CODE_DOOR_GET_DOOR {
			if aswmsg, err_msg := strconv.Atoi(data.AswMsg); err_msg == nil {
				global.LOG.Debug(fmt.Sprintf("门禁变化[%v]: %v", sn, data.AswMsg))
				// 修改状态
				device.Status = aswmsg
				err = service.DeviceEdit(*device)
				if err != nil {
					return err
				}
				// 添加记录
				dlog := &model.DeviceLog{DeviceID: device.ID, Status: aswmsg, Value: ""}
				err = service.DeviceLogAdd(*dlog)
				if err != nil {
					return err
				}
			}
		}
	}
	if device.Tag == "switch" {
		// fmt.Println("源控变化")
		if data.AswCode == fsc.CODE_SWITCH_GET_SWITCH {
			if aswmsg, err_msg := strconv.Atoi(data.AswMsg); err_msg == nil {
				global.LOG.Debug(fmt.Sprintf("源控变化[%v]: %v", sn, data.AswMsg))
				// 修改状态
				device.Status = aswmsg
				err = service.DeviceEdit(*device)
				if err != nil {
					return err
				}
				// 添加记录
				dlog := &model.DeviceLog{DeviceID: device.ID, Status: aswmsg, Value: ""}
				err = service.DeviceLogAdd(*dlog)
				if err != nil {
					return err
				}
			}
		}
	}
	return nil
}

// 源控开关状态
var switch_status = 0

// func (m *Client) job_check_lock() {
func job_check_lock(m MQTT.Client) {
	devices, err := service.DeviceGetLock()
	if err != nil {
		global.LOG.Error(fmt.Sprintf("%v", err))
		return
	}
	offline := false
	infrared := 0
	door := 0
	switch_now := 0
	for _, d := range devices {
		// 设备未连锁，跳过判断
		if d.Lock == 0 {
			continue
		}
		// 设备处于离线状态，通知连锁错误
		if d.Online == 0 {
			offline = true
			break
		}
		// 红外检测到有人
		if d.Tag == "infrared" {
			if d.Status == 1 {
				infrared = 1
			}
		}
		// 门禁检测到开启
		if d.Model == "rg602" {
			if d.Status == 1 {
				door = 1
			}
		}
	}
	// 设备未离线的情况下
	if offline == false {
		// 开启
		if infrared == 0 && door == 0 {
			switch_now = 1
		} else {
			switch_now = 0
		}

	}
	// 控制源控
	if switch_status != switch_now {
		switch_status = switch_now
		if switch_status == 1 {
			// info := fmt.Sprintf(`{"code":"%v"}`, fsc.CODE_SYSTEM_SWITCH_OPEN)
			m.Publish("fsc/sys", 0, false, fmt.Sprintf(`{"code":"%v"}`, fsc.CODE_SYSTEM_SWITCH_OPEN))
			global.LOG.Debug("源控开关->开启")
			// global.LOG.Info("源控开关->开启")
		}
		if switch_status == 0 {
			// info := fmt.Sprintf(`{"code":"%v"}`, fsc.CODE_SYSTEM_SWITCH_CLOSE)
			m.Publish("fsc/sys", 0, false, fmt.Sprintf(`{"code":"%v"}`, fsc.CODE_SYSTEM_SWITCH_CLOSE))
			global.LOG.Debug("源控开关->关闭")
			// global.LOG.Info("源控开关->关闭")
		}
	}

}

var messageHandler MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
	// fmt.Println("************************** lock message ****************************")
	// fmt.Printf("topic: %s\n", msg.Topic())
	// fmt.Printf("message: %s\n", msg.Payload())
	// global.LOG.Info("***** LOCK *****")
	// 匹配设备上传信息
	reg_tx, err := regexp.Compile(`^fsc/(.*?)/(.*?)/tx`)
	if err != nil {
		global.LOG.Error(fmt.Sprintf("%v", err))
		return
	}
	if reg_tx.MatchString(msg.Topic()) == true {
		result := reg_tx.FindStringSubmatch(msg.Topic())
		sn := result[2]
		// 转换数据为json
		var data AswData
		err := json.Unmarshal([]byte(msg.Payload()), &data)
		if err != nil {
			global.LOG.Error(fmt.Sprintf("%v", err))
			return
		}
		err = StatusDeal(sn, data)
		if err != nil {
			global.LOG.Error(fmt.Sprintf("%v", err))
			return
		} else {
			job_check_lock(client)
		}
	}
}

type Client struct {
	MQTT.Client
	Host     string
	ClientID string
	UserName string
	Password string
}

type Message struct {
	ClientID string `json:"clientId"`
	Type     string `json:"type"`
	Data     string `json:"data,omitempty"`
	Time     int64  `json:"time"`
}

func (m *Client) NewClient() {
	ClientID := "go-lock-" + utils.GenerateTimeMD5()[0:8]
	opts := MQTT.NewClientOptions()
	opts.AddBroker(global.CONFIG.Emqx.Host)
	opts.SetClientID(ClientID)
	opts.SetUsername(global.CONFIG.Emqx.Username)
	opts.SetPassword(global.CONFIG.Emqx.Password)
	opts.SetCleanSession(true)
	opts.SetAutoReconnect(true)
	opts.SetKeepAlive(120 * time.Second)
	opts.SetPingTimeout(10 * time.Second)
	opts.SetWriteTimeout(10 * time.Second)
	opts.SetOnConnectHandler(func(client MQTT.Client) {
		// 连接被建立后的回调函数
		global.LOG.Info(fmt.Sprintf(" Mqtt is connected! clientId: %v", ClientID))
		// 重连后重新订阅
		m.Subscribe()
	})
	opts.SetConnectionLostHandler(func(client MQTT.Client, err error) {
		// 连接被关闭后的回调函数
		global.LOG.Info(fmt.Sprintf("Mqtt is disconnected! clientId: %v reason: %v", ClientID, err.Error()))
	})

	m.Client = MQTT.NewClient(opts)
}

func (m *Client) Connect() {
	global.LOG.Info("connect")

	token := m.Client.Connect()
	if token.Wait() && token.Error() != nil {
		global.LOG.Error(fmt.Sprintf("%v", token.Error()))
	}
}

func (m *Client) DisConnect() {
	fmt.Println("disconnect")
	m.Client.Disconnect(250)
}

func (m *Client) Subscribe() {
	global.LOG.Info("subscribe")
	topics := make(map[string]byte)
	// topics["fsc/+/+/tx"] = 0
	for _, v := range global.CONFIG.Emqx.LockTopics {
		topics[v] = 0
	}
	global.LOG.Info(fmt.Sprintf("%v", topics))
	// token := m.Client.Subscribe("dqt201/+/tx", 0, messageHandler)
	token := m.Client.SubscribeMultiple(topics, messageHandler)
	if token.Wait() && token.Error() != nil {
		global.LOG.Error(fmt.Sprintf("%v", token.Error()))
	}
}

func (m *Client) Pub() {
	global.LOG.Info("publish")
	s := time.Now().String()
	token := m.Client.Publish("date", 0, false, s)
	if token.Wait() && token.Error() != nil {
		global.LOG.Error(fmt.Sprintf("%v", token.Error()))
	}
}

func (m *Client) Run() {

	m.NewClient()
	m.Connect()

	// var wg sync.WaitGroup
	// go func() {
	// 	for {
	// 		time.Sleep(time.Millisecond * 100)
	// 		m.job_check_lock()
	// 	}
	// }()
	// wg.Add(1)
	// go m.job_check_lock()
	// 定义一个cron运行器
	// c := cron.New()
	// c.AddFunc("*/1 * * * * *", m.job_check_lock)
	// c.Start()
}
